﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Nop.Core;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using Nop.Plugin.Payments.PagSeguro.Models;
using Nop.Services.Configuration;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Web.Framework;
using Nop.Web.Framework.Controllers;

namespace Nop.Plugin.Payments.PagSeguro.Controllers
{
    public class PaymentPagSeguroController : BaseNopPaymentController
    {
        private readonly ISettingService _settingService;
        private readonly IOrderService _orderService;
        private readonly IOrderProcessingService _orderProcessingService;
        private readonly ILogger _logger;
        private readonly PagSeguroPaymentSettings _pagSeguroPaymentSettings;

        public PaymentPagSeguroController(ISettingService settingService, 
            IPaymentService paymentService, IOrderService orderService, 
            IOrderProcessingService orderProcessingService, 
            ILogger logger, PagSeguroPaymentSettings pagSeguroPaymentSettings,
            PaymentSettings paymentSettings, ILocalizationService localizationService)
        {
            this._settingService = settingService;
            this._orderService = orderService;
            this._orderProcessingService = orderProcessingService;
            this._logger = logger;
            this._pagSeguroPaymentSettings = pagSeguroPaymentSettings;
        }

        [AdminAuthorize]
        [ChildActionOnly]
        public ActionResult Configure()
        {
            var model = new ConfigurationModel();
            model.Email = _pagSeguroPaymentSettings.Email;
            model.Token = _pagSeguroPaymentSettings.Token;

            return View("Nop.Plugin.Payments.PagSeguro.Views.PaymentPagSeguro.Configure", model);
        }

        [HttpPost]
        [AdminAuthorize]
        [ChildActionOnly]
        public ActionResult Configure(ConfigurationModel model)
        {
            if (!ModelState.IsValid)
                return Configure();

            //save settings
            _pagSeguroPaymentSettings.Email = model.Email;
            _pagSeguroPaymentSettings.Token = model.Token;

            _settingService.SaveSetting(_pagSeguroPaymentSettings);

            return View("Nop.Plugin.Payments.PagSeguro.Views.PaymentPagSeguro.Configure", model);
        }

        [NonAction]
        public override IList<string> ValidatePaymentForm(FormCollection form)
        {
            var warnings = new List<string>();
            return warnings;
        }

        [ChildActionOnly]
        public ActionResult PaymentInfo()
        {
            return View("Nop.Plugin.Payments.PagSeguro.Views.PaymentPagSeguro.PaymentInfo");
        }

        [NonAction]
        public override ProcessPaymentRequest GetPaymentInfo(FormCollection form)
        {
            var paymentInfo = new ProcessPaymentRequest();
            return paymentInfo;
        }

        [NonAction]
        public ActionResult PaymentReturn()
        {
            _logger.Error("PaymentReturn - chamada inválida.");
            return Content("");
        }

        /// <summary>
        /// PaymentReturn utilizando API de notificação automática do PagSeguro
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ActionResult PaymentReturn(FormCollection model)
        {
            Order _order = _orderService.GetOrderByGuid(new Guid(model["Referencia"]));
            try
            {
                TimeZoneInfo timeZoneInfo;
                DateTime curretDateTime;
                timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("E. South America Standard Time");
                curretDateTime = TimeZoneInfo.ConvertTime(DateTime.Now, timeZoneInfo);

                if (model == null)
                {
                    _logger.Error("PaymentReturn - FormCollection is null.");
                    return null;
                }

                if (model.Count == 0)
                {
                    _logger.Error("PaymentReturn - FormCollection count is zero.");
                    return null;
                }

                if (string.IsNullOrEmpty(model["Referencia"]))
                {
                    return null;
                }

                string postMessage = string.Empty;
                foreach (var key in model.AllKeys)
                {
                    if (!string.IsNullOrEmpty(postMessage))
                        postMessage += "&";

                    postMessage += string.Format("{0}: {1}", key.ToString(), model[key]);
                }

                if (!string.IsNullOrEmpty(postMessage))
                    _logger.Information(string.Format("HttpPostMessage: ", postMessage));

                if (_order == null)
                {
                    _logger.Error("Pedido não encontrado. " + model["Referencia"]);
                    return null;
                }

                switch (model["TipoFrete"])
                {
                    case "SD":
                        _order.ShippingMethod = "Sedex";
                        break;
                    case "EN":
                        _order.ShippingMethod = "PAC";
                        break;
                    default:
                        _order.ShippingMethod = model["TipoFrete"];
                        break;
                }

                decimal valorFrete = 0;
                if (decimal.TryParse(model["ValorFrete"], out valorFrete))
                    _order.OrderShippingExclTax = valorFrete;

                if (!string.IsNullOrEmpty(model["Anotacao"]))
                {
                    _order.OrderNotes.Add(new OrderNote()
                    {
                        Note = model["Anotacao"],
                        CreatedOnUtc = curretDateTime,
                        DisplayToCustomer = true
                    });
                }

                string tipoPagamento = model["TipoPagamento"];
                
                switch (model["StatusTransacao"])
                {
                    case "Completo":
                        _order.PaymentStatus = PaymentStatus.Authorized;
                        _orderProcessingService.MarkOrderAsPaid(_order);
                        break;
                    case "Aguardando Pagto":
                        _order.PaymentStatus = PaymentStatus.Pending;
                        break;
                    case "Aprovado":
                        _order.PaymentStatus = PaymentStatus.Paid;
                        _order.PaidDateUtc = DateTime.Now;
                        _orderProcessingService.MarkAsAuthorized(_order);
                        break;
                    case "Em Análise":
                        _order.PaymentStatus = PaymentStatus.Pending;
                        break;
                    case "Cancelado":
                        _orderProcessingService.CancelOrder(_order, true);
                        break;
                }

                
                OrderNote note = new OrderNote();
                note.CreatedOnUtc = curretDateTime;
                note.DisplayToCustomer = true;
                note.Note = string.Format("Forma de pagamento: {0}. {1}.", tipoPagamento, model["StatusTransacao"]);
                _order.OrderNotes.Add(note);

                _orderService.UpdateOrder(_order);
            }
            catch (Exception ex)
            {
                string erro = string.Format("PaymentReturn - {0} || {1} || {2} ", model.ToString(), model.AllKeys.ToString(), ex.Message.ToString());

                _logger.Error(erro);

                if (_order.OrderStatus != OrderStatus.Cancelled)
                    _orderProcessingService.CancelOrder(_order, true);
            }

            return Content("");
        }
    }
}
